// Copyright 2023 Huawei Cloud Computing Technology Co., Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef MSGHEAD_H
#define MSGHEAD_H

#include <string>
#include <arpa/inet.h>
#include <endian.h>
#include <ratio>
#include "Log/logging.h"

enum VMIMsgType : uint8_t {
    Invalid = 0,
    HEARTBEAT = 1,
    GameControl = 2,
    GL = 3,
    Video = 4,
    Audio = 5,
    Recorder = 6,
    TouchInput = 7,
    InputMethodEditor = 8,
    Sensor = 9,
    GPS = 10,
    ORIENTATION = 11,
    ClientRPC = 12,
    VideoEncodeConf = 13,
    VideoEncodeStatistics = 14,
    VideoStreamYuv = 15,
    VideoStreamH264 = 16,
    Camera = 17,
    End
};  // 结合分片标志，type最高两位作为分片标志，type本身取值不可超6位，即63。

const std::string SENSOR_SHAREMEM_NAME = "sensor";
const std::string AUDIO_SHAREMEM_NAME = "audio";
const std::string RECORD_SHAREMEM_NAME = "record";
const std::string GPS_SHAREMEM_NAME = "gps";
const std::string INPUT_SHAREMEM_NAME = "touch";
const std::string IME_SHAREMEM_NAME = "ime";
const std::string ORIENTATION_SHAREMEM_NAME = "orientation";
const std::string VIDEO_SHAREMEM_NAME = "video";

enum FRAGMENT {
    SINGLE_FRAGMENT = 0x0,  // 两位标志位全0表示完整消息，没有分片
    FIRST_FRAGMENT = 0x2, // 两位标志位10表示首分片
    MIDDLE_FRAGMENT = 0x3,  // 两位标志位11表示中间分片
    END_FRAGMENT = 0x1,  // 两位标志位01表示尾分片
};

enum MESSAGE_POSITION {
    MSG_BYTE_OFFSET = 8,
    MSG_TYPE_OFFSET = 0,
    MSG_TYPE_MASK = 0x3F,
    MSG_FLAG_MASK = 0xC0,
    MSG_FLAG_OFFSET = 6,
    MSG_FLAG_SIZE = 2,
    MSG_FLAG_BYTE_MASK = 0x3,
    MAGIC_WORD_MASK = 0xFF,
};

const uint16_t VMI_STREAM_DELIMITER_MAGICWORD = 0x5A5A;

#define CREATE_VMI_CHECKSUM(type, flag) \
    (((type | (flag << MSG_FLAG_OFFSET)) + \
    ((VMI_STREAM_DELIMITER_MAGICWORD >> MSG_BYTE_OFFSET) & MAGIC_WORD_MASK) + \
    (VMI_STREAM_DELIMITER_MAGICWORD & MAGIC_WORD_MASK)) & MAGIC_WORD_MASK)

struct StreamMsgHead {
private:
    uint16_t magicword;
    uint8_t checksum;
    uint8_t flagType;  // flag:2,type:6。结合分片标志，type最高两位作为分片标志，type本身取值不可超6位，即63。
    uint32_t size;

public:
    bool verifyMsgHead()
    {
        if ((uint16_t)ntohs(this->magicword) == VMI_STREAM_DELIMITER_MAGICWORD) {
            return (this->checksum == (((this->flagType) + (((uint16_t)ntohs(this->magicword) >> MSG_BYTE_OFFSET) &
                    MAGIC_WORD_MASK) + ((uint16_t)ntohs(this->magicword) & MAGIC_WORD_MASK)) & MAGIC_WORD_MASK));
        } else {
            return false;
        }
    }

    void setMagicWord() { this->magicword = (uint16_t)htons(VMI_STREAM_DELIMITER_MAGICWORD); }

    void setCheckSum(uint8_t checksum) { this->checksum = checksum; }

    uint32_t getPayloadSize() const { return (uint32_t)ntohl(size); }

    void setPayloadSize(uint32_t size) { this->size = htonl(size); }

    VMIMsgType getType() const { return static_cast<VMIMsgType>(this->flagType & MSG_TYPE_MASK); }

    void setType(VMIMsgType type)
    {
        this->flagType = (this->flagType & MSG_FLAG_MASK) | ((uint8_t)type & MSG_TYPE_MASK);
    }

    uint8_t getFlag() const { return (this->flagType >> MSG_FLAG_OFFSET) & MSG_FLAG_BYTE_MASK; }

    void setFlag(uint8_t flag)
    {
        this->flagType = (this->flagType & MSG_TYPE_MASK) | ((flag & MSG_FLAG_BYTE_MASK) << MSG_FLAG_OFFSET);
    }
} __attribute__((packed));

enum MESSAGE_HEAD {
    FRAGMENT_SIZE_FULL = 1420,

    // 分片长度设置不可过大，按照带宽计算发送一个分片时间不可超过毫秒级，否则就失去了分片的意义
    FRAGMENT_SIZE   = FRAGMENT_SIZE_FULL - sizeof(StreamMsgHead),

    // 包括消息头，最大的消息长度, 32 * 1024 * 1024
    MAX_MSG_SIZE    = 33554432,
};
#endif  // MSGHEAD_H
